/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    hlw8012.c
  * @brief   Implementation file for HLW8012 power monitoring IC driver
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "hlw8012.h"
#include "gpio.h"
#include "stm32f1xx_hal.h"
#include "tim.h"
#include "stm32f1xx_ll_exti.h"
#include "stm32f1xx_ll_system.h"

/* Private typedef -----------------------------------------------------------*/

/* Private define ------------------------------------------------------------*/

/* Private macro -------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/
volatile uint32_t hlw8012_voltage_count = 0;  // 电压脉冲计数
volatile uint32_t hlw8012_last_time = 0;      // 上次测量时间
float input_voltage = 0.0f;                   // 输入电压值
float frequency = 0;
/* Private function prototypes -----------------------------------------------*/
static void HLW8012_VoltageInterruptHandler(void);

/* Exported functions --------------------------------------------------------*/

/**
  * @brief  初始化HLW8012
  * @retval None
  */
void HLW8012_Init(void)
{
  // 初始化变量
  hlw8012_voltage_count = 0;
  hlw8012_last_time = 0;
  input_voltage = 0.0f;
  
  // 禁用中断，默认不启用
  HLW8012_DisableInterrupt();
}

/**
  * @brief  启用HLW8012电压中断
  * @retval None
  */
void HLW8012_EnableInterrupt(void)
{
  // 清除之前的计数
  hlw8012_voltage_count = 0;
  hlw8012_last_time = HAL_GetTick();
  
  // 启用EXTI3中断
  NVIC_EnableIRQ(EXTI3_IRQn);
  
  // 配置PA3为EXTI3输入源 (STM32F1使用AFIO而不是SYSCFG)
  AFIO->EXTICR[0] &= ~AFIO_EXTICR1_EXTI3;
  AFIO->EXTICR[0] |= AFIO_EXTICR1_EXTI3_PA;
  
  // 配置EXTI3为双边沿触发
  LL_EXTI_EnableRisingTrig_0_31(LL_EXTI_LINE_3);
  LL_EXTI_EnableFallingTrig_0_31(LL_EXTI_LINE_3);
  
  // 启用EXTI3中断线
  LL_EXTI_EnableIT_0_31(LL_EXTI_LINE_3);
}

/**
  * @brief  禁用HLW8012电压中断
  * @retval None
  */
void HLW8012_DisableInterrupt(void)
{
  // 禁用EXTI3中断线
  LL_EXTI_DisableIT_0_31(LL_EXTI_LINE_3);
  
  // 禁用EXTI3中断
  NVIC_DisableIRQ(EXTI3_IRQn);
}

/**
  * @brief  读取电压值
  * @retval 电压值（V）
  */
float HLW8012_ReadVoltage(void)
{
  uint32_t current_time = HAL_GetTick();
  uint32_t duration_ms = current_time - hlw8012_last_time;
  
  if (duration_ms > 0)
  {
    // 计算频率（Hz）
     frequency = (float)hlw8012_voltage_count * 1000.0f / duration_ms;
    
    // 根据HLW8012规格书，CF1引脚输出频率与电压有效值成正比
    // 正确的计算公式：Vrms = 频率 * HLW8012_VOLTAGE_FACTOR
    input_voltage = frequency * HLW8012_VOLTAGE_FACTOR;
    
    // 电压范围检查，确保结果在合理范围内
    if (input_voltage < HLW8012_VOLTAGE_RANGE_MIN)
    {
      input_voltage = 0.0f; // 低于测量范围，视为无输入
    }
    else if (input_voltage > HLW8012_VOLTAGE_RANGE_MAX)
    {
      input_voltage = HLW8012_VOLTAGE_RANGE_MAX; // 超出测量范围，限制在最大值
    }
  }
  
  return input_voltage;
}

/* Private functions ---------------------------------------------------------

/**
  * @brief  HLW8012测量任务
  * @param  argument: Not used
  * @retval None
  */
void HLW8012_MeasurementTask(void *argument)
{
  /* 初始化 */
  HLW8012_Init();
  
  /* Infinite loop */
  for(;;)
  {
    // 启用中断开始测量
    HLW8012_EnableInterrupt();
    
    // 等待采样时间
    osDelay(HLW8012_SAMPLE_DURATION_MS);
    
    // 禁用中断结束测量
    HLW8012_DisableInterrupt();
    
    // 计算并读取电压
    input_voltage = HLW8012_ReadVoltage();
    
    // 将HLW8012测量的电压值更新到系统变量ac_v中
    // 这样freertos.c中的代码就能将其正确存储到rtu_buff[139]中
    extern uint16_t ac_v;
		extern float ac_v_f;
		extern uint16_t rtu_buff[1090];
    ac_v = (uint16_t)(input_voltage * 10.0f);
    rtu_buff[139] = ac_v;
	  ac_v_f = ac_v/10;	
    // 等待下一次测量间隔
    osDelay(HLW8012_MEASUREMENT_INTERVAL_MS - HLW8012_SAMPLE_DURATION_MS);
  }
}

/* USER CODE BEGIN 1 */
// 这里可以添加用户自定义的扩展函数
/* USER CODE END 1 */